﻿using System;
using System.Collections.Generic;
using System.Drawing.Design;
using System.Linq;
using System.Windows.Forms.Design;
using devtm.Editor.TypeSelector;
using DslModeling = global::Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling;
using System.Windows.Forms;
using System.Reflection;
using Mono.Cecil;
using CustomTypes.Mono.Extensions;
using CodeDomHelper.Types;

namespace devtm.AutoMapper
{

	public class SelectListModelViews : UITypeEditor
	{

		protected DslModeling.Store Store;
		protected ItemMap Instance;

		TypeExpression Source;
		TypeExpression Target;
			

		public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value)
		{

			IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
			if (edSvc != null)
			{

				bool isSource = context.PropertyDescriptor.Name.Contains("Source");

				if (context.Instance.GetType().IsArray)
					Instance = ((Object[])context.Instance)[0] as ItemMap;
				else
					Instance = context.Instance as ItemMap;
				Store = Instance.Store;

				Source = CodeDomHelper.Types.BuildTypeExpression.Analyse(Instance.SourceType);
				Target = CodeDomHelper.Types.BuildTypeExpression.Analyse(Instance.TargetType);

				TreeView control = new TreeView() { CheckBoxes = false };

				var models = Store2DTE.GetOtherModels(Store).ToList();

				#region Build List
				
				foreach (var item in models)
				{
					TreeNode t1 = new TreeNode() { Text = item.Name, Tag = item };
					// on ouvre le store
					using (Store store = StoreHelper.GetStore(item))
					{
						var e = store.ElementDirectory;
						if (e != null)
						{
							// on recupere le model
							MappingModel f = e.AllElements.FirstOrDefault() as MappingModel;
							if (f != null)
							{
								GetNodeMembers(t1, f);
								if (t1.Nodes.Count > 0)
									control.Nodes.Add(t1);
							}

						}
					}

				}

				#endregion

				#region Select current

				string[] _select = ((string)value).Split('!');

				if (_select.Length ==2)
					foreach (TreeNode item in control.Nodes)
						if (_select[0] == item.Text)
						{
							item.Expand();
							foreach (TreeNode item2 in item.Nodes)
							{
								var m = item2.Tag as Mapper;
								if (m.Name ==_select[1])
									control.SelectedNode = item2;
							}
						}

				#endregion
			   
				var d = DateTime.Now;

				control.AfterSelect +=
				(sender, e) =>
				{

					if (DateTime.Now.Subtract(d).Seconds < 1)
						return;


					if (_select[0] != e.Node.Text)
						if (e.Node.Tag is Mapper)
						{

							value = e.Node.Parent.Text + 
								"!" +
								(e.Node.Tag as Mapper).Name;

							edSvc.CloseDropDown();

						}
					

				};

				edSvc.DropDownControl(control);
				control.Focus();
			}

			return value;

		}


		private void GetNodeMembers(TreeNode t, MappingModel models)
		{


			var s1 = Source.IsGeneric
			? Source.SubType.TypeName
			: Source.TypeName;

			var t1 = Target.IsGeneric
				? Target.SubType.TypeName
				: Target.TypeName;



			foreach (Mapper mapper in models.Mappers.OrderBy(m => m.MappingSource.TypeElement.Name))
			{
				string SAssemblyQualifiedName = mapper.MappingSource.TypeElement.AssemblyQualifiedName;
				if (s1 == SAssemblyQualifiedName || Source.Equals(SAssemblyQualifiedName))
				{
					string TAssemblyQualifiedName = mapper.MappingDestination.TypeElement.AssemblyQualifiedName;
					if (t1 == TAssemblyQualifiedName || Target.Equals(TAssemblyQualifiedName))
					{
						TreeNode t2 = new TreeNode()
						{
							Text = string.Format("{0} -> {1}",
							mapper.MappingSource.TypeElement.Name,
							mapper.MappingDestination.TypeElement.Name),
							Tag = mapper,
							ToolTipText = mapper.Name,
						};

						t.Nodes.Add(t2);

					}

				}
			}
			
		}

	  
		public override bool IsDropDownResizable { get { return true; } }

		public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
		{

			if (context != null)
			{

				if (context.Instance.GetType().IsArray)
					Instance = ((Object[])context.Instance)[0] as ItemMap;
				else
					Instance = context.Instance as ItemMap;

				if (Instance != null)
					return UITypeEditorEditStyle.DropDown;
			}

			return UITypeEditorEditStyle.None;

		}

		private static TypeElement GetTypeElement(System.ComponentModel.ITypeDescriptorContext context, Mapper mapper)
		{
			if (context.PropertyDescriptor.Name.Contains("Source"))
				return mapper.MappingSource.TypeElement;

			return mapper.MappingDestination.TypeElement;

		}


	}
}
